module sw.checker;

struct CheckerError{
  int line;
  string msg;
}

CheckerError* newCheckerError(int line, string msg){
  CheckerError* ce = new CheckerError;
  *ce = CheckerError(line, msg);
  return ce;
}

/**
 * 構文チェッカ
 * Bugs: 未ローカライズ
 *       unittestがクラッシュしてる
 */
CheckerError* check(string source){
  int l, tag;
  bool backslash;
  foreach(i, c; source){
    if(backslash){
      backslash = false;
      continue;
    }
    if(tag == 1){
      if(c < 'a' || c > 'z')
        return newCheckerError(i, "a-zが来るべきなのに「"~c~"」が来ています。");
      tag = 2;
      continue;
    }else if(tag == 2){
      if((c < 'a' || c > 'z') && c != ':'){
        if(c == '\n' || c == '\r' || c == ' ' || c == '\t'){
          tag = 0;
          continue;
        }else if(c == ']'){
          tag = 0;
          l--;
          continue;
        }
        return newCheckerError(i, "a-z、:、改行、空白が来るべきなのに「"~c~"」が来ています。");
      }
      continue;
    }
    switch(c){
      case '\\':
        backslash = true;
        break;
      case '[':
        l++;
        tag = 1;
        break;
      case ']':
        if(l==0)
            return newCheckerError(i, "]が多すぎます。");
        l--;
        break;
      default:
    }
  }
  if(l)
    return newCheckerError(source.length, "]が足りません。");
  if(backslash)
    return newCheckerError(source.length, "エスケープする文字がありません。");
  return null;
}

unittest{
/*  assert(check("[aa]").line==-1);
  assert(check("[aa:bb]").line==-1);
  assert(check("[aa-bb]").line==3);
  assert(check("[aa bb,cc]").line==-1);
  assert(check("[aa bb[cc dd]]").line==-1);
  assert(check("]").line==0);
  assert(check("[]").line==1);
  assert(check("[aa [bb]").line==7);
  assert(check("\\").line==0);
  assert(check("[aa]]").line==4);*/
}
